"""
Validation utilities for business logic.
"""
from datetime import datetime, time
from typing import Optional, List, Tuple
from sqlalchemy.orm import Session
from app.models.booking import Booking
from app.models.schedule import Schedule
from uuid import UUID


def check_time_overlap(
    start_time1: datetime, 
    end_time1: datetime, 
    start_time2: datetime, 
    end_time2: datetime
) -> bool:
    """
    Check if two time ranges overlap.
    
    Args:
        start_time1: Start time of first range
        end_time1: End time of first range
        start_time2: Start time of second range
        end_time2: End time of second range
        
    Returns:
        True if ranges overlap, False otherwise
    """
    return start_time1 < end_time2 and start_time2 < end_time1


def validate_booking_time_range(
    db: Session,
    room_id: UUID,
    start_time: datetime,
    end_time: datetime,
    exclude_booking_id: Optional[UUID] = None
) -> Tuple[bool, List[Booking]]:
    """
    Validate if a booking time range is available (no conflicts).
    
    Args:
        db: Database session
        room_id: The room ID to check
        start_time: Proposed start time
        end_time: Proposed end time
        exclude_booking_id: Optional booking ID to exclude from check (for updates)
        
    Returns:
        Tuple of (is_available, conflicting_bookings)
    """
    from app.models.booking import BookingStatus
    
    # Query existing bookings for the same room
    query = db.query(Booking).filter(
        Booking.room_id == room_id,
        Booking.status.in_([BookingStatus.PENDING, BookingStatus.CONFIRMED])
    )
    
    # Exclude specific booking if updating
    if exclude_booking_id:
        query = query.filter(Booking.id != exclude_booking_id)
    
    # Get all bookings for this room
    existing_bookings = query.all()
    
    # Check for overlaps
    conflicting_bookings = []
    for booking in existing_bookings:
        # Use getattr to safely access the values
        booking_start = getattr(booking, 'start_time', None)
        booking_end = getattr(booking, 'end_time', None)
        
        if booking_start and booking_end and check_time_overlap(start_time, end_time, booking_start, booking_end):
            conflicting_bookings.append(booking)
    
    is_available = len(conflicting_bookings) == 0
    return is_available, conflicting_bookings


def validate_booking_within_schedule(
    db: Session,
    room_id: UUID,
    start_time: datetime,
    end_time: datetime
) -> Tuple[bool, str]:
    """
    Validate if booking time is within room's open hours.
    
    Args:
        db: Database session
        room_id: The room ID to check
        start_time: Proposed start time
        end_time: Proposed end time
        
    Returns:
        Tuple of (is_valid, error_message)
    """
    # Debug logging
    print(f"DEBUG: Validating booking for room {room_id}")
    print(f"DEBUG: Start time: {start_time} (type: {type(start_time)})")
    print(f"DEBUG: End time: {end_time} (type: {type(end_time)})")
    print(f"DEBUG: Start time tzinfo: {start_time.tzinfo}")
    print(f"DEBUG: End time tzinfo: {end_time.tzinfo}")
    
    # Get the day of week (0=Monday, 6=Sunday)
    day_of_week = start_time.weekday()
    print(f"DEBUG: Day of week: {day_of_week}")
    
    # Get schedule for this room and day
    schedule = db.query(Schedule).filter(
        Schedule.room_id == room_id,
        Schedule.day_of_week == day_of_week
    ).first()
    
    # If no schedule exists, assume 24/7 availability
    if not schedule:
        print("DEBUG: No schedule found, assuming 24/7 availability")
        return True, ""
    
    # Check if room is available on this day
    # Use getattr to safely access the value
    is_available = getattr(schedule, 'is_available', True)
    if not is_available:
        return False, f"Room is not available on this day"
    
    # Convert datetime to time for comparison
    booking_start_time = start_time.time()
    booking_end_time = end_time.time()
    
    print(f"DEBUG: Booking start time: {booking_start_time}")
    print(f"DEBUG: Booking end time: {booking_end_time}")
    
    # Use getattr to safely access the values
    schedule_open_time = getattr(schedule, 'open_time', None)
    schedule_close_time = getattr(schedule, 'close_time', None)
    
    print(f"DEBUG: Schedule open time: {schedule_open_time}")
    print(f"DEBUG: Schedule close time: {schedule_close_time}")
    
    if not schedule_open_time or not schedule_close_time:
        return True, ""  # No schedule defined, assume available
    
    # Log for debugging (commented out)
    # print(f"DEBUG: Booking {booking_start_time} to {booking_end_time}")
    # print(f"DEBUG: Schedule {schedule_open_time} to {schedule_close_time}")
    
    # Check if booking is within open hours
    # Allow bookings that start exactly at open time (inclusive)
    if booking_start_time < schedule_open_time:
        return False, f"Booking starts before room opens at {schedule_open_time}"
    
    # Allow bookings that end exactly at close time (inclusive)
    # This is the key change - use >= instead of > to allow bookings ending at closing time
    if booking_end_time > schedule_close_time:
        return False, f"Booking ends after room closes at {schedule_close_time}"
    
    # Additional validation: end time must be after start time
    if booking_end_time <= booking_start_time:
        return False, "Booking end time must be after start time"
    
    return True, ""
